windbg时间穿梭——利用Time Travel Debugging更方便地调试漏洞

下面使用windbg是新版的windbg,叫windbg preview,需要在微软商店(Microsoft Store)中下载安装

新版的windbg具有更现代的视觉效果,速度更快,更完善的脚本编写体验以及Time Travel Debugging 特性

需要注意的是,Time Travel Debugging特性的开启需要以管理员权限运行,之后使用advanced打开并勾选对应的选项即可,最后配置一下记录的保存路径即可

当然你也可以attach到正在运行的程序,或者打开别人的trace file

有了Time Travel Debugging,你几乎可以像本地看电影一样,不断来回脱动进度条,而且这个还是本地化,免去了查找漏洞软件,搭建环境,验证漏洞的烦恼,只需要拿到别人的TTD的记录文件即可,而且调试过程地址还不会变,爽不爽。

Time Travel Debugging 初探

我们随便找一个windows程序,看看这个新特性

一开始载入没什么反应,以为出什么事了,原来是这个特性载入程序,速度太慢了

对于我们常用的p,t,g,假如想反向执行,只需在指令后面加个”-“号

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
0:000> p
Time Travel Position: 63:3F

**** WARNING loaded *kernel* extension dll for usermode

eax=559b1944 ebx=02bfe000 ecx=00000001 edx=0099b720 esi=00991100 edi=00991100
eip=00992158 esp=0098f9c0 ebp=0098f9dc iopl=0 nv up ei pl nz na po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000202
learnCFG!main+0x8:
00992158 b8cccccccc mov eax,0CCCCCCCCh
0:000> p
Time Travel Position: 63:40

**** WARNING loaded *kernel* extension dll for usermode

eax=cccccccc ebx=02bfe000 ecx=00000001 edx=0099b720 esi=00991100 edi=00991100
eip=0099215d esp=0098f9c0 ebp=0098f9dc iopl=0 nv up ei pl nz na po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000202
learnCFG!main+0xd:
0099215d 8945ec mov dword ptr [ebp-14h],eax ss:002b:0098f9c8=0098f9d4
0:000> p-
Time Travel Position: 63:3F

**** WARNING loaded *kernel* extension dll for usermode

eax=559b1944 ebx=02bfe000 ecx=00000001 edx=0099b720 esi=00991100 edi=00991100
eip=00992158 esp=0098f9c0 ebp=0098f9dc iopl=0 nv up ei pl nz na po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000202
learnCFG!main+0x8:
00992158 b8cccccccc mov eax,0CCCCCCCCh

可以看到,假如我们一步小心,执行过了,还可以回退,可以回到当初的状态看看寄存器,内存,这是相当好的东西,有后悔药吃了。

有时候我们执行过了头,想要跟进去那个函数,也是可以回头进去的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
eax=12fd94d0 ebx=02bfe000 ecx=009913a0 edx=00000000 esi=0098f9c0 edi=0098f9bc
eip=009921d1 esp=0098f9bc ebp=0098f9dc iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
learnCFG!main+0x81:
009921d1 ff1500e09900 call dword ptr [learnCFG!__guard_check_icall_fptr (0099e000)] ds:002b:0099e000={ntdll!LdrpValidateUserCallTarget (77408be0)}
0:000> p
Time Travel Position: 67:85

**** WARNING loaded *kernel* extension dll for usermode

eax=00132274 ebx=02bfe000 ecx=009913a0 edx=10100444 esi=0098f9c0 edi=0098f9bc
eip=009921d7 esp=0098f9bc ebp=0098f9dc iopl=0 nv up ei pl zr na pe cy
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000247
learnCFG!main+0x87:
009921d7 3bfc cmp edi,esp
0:000> p-
Time Travel Position: 67:79

**** WARNING loaded *kernel* extension dll for usermode

eax=12fd94d0 ebx=02bfe000 ecx=009913a0 edx=00000000 esi=0098f9c0 edi=0098f9bc
eip=009921d1 esp=0098f9bc ebp=0098f9dc iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
learnCFG!main+0x81:
009921d1 ff1500e09900 call dword ptr [learnCFG!__guard_check_icall_fptr (0099e000)] ds:002b:0099e000={ntdll!LdrpValidateUserCallTarget (77408be0)}
0:000> t
Time Travel Position: 67:7D

**** WARNING loaded *kernel* extension dll for usermode

eax=00009913 ebx=02bfe000 ecx=009913a0 edx=009b0000 esi=0098f9c0 edi=0098f9bc
eip=77408beb esp=0098f9b8 ebp=0098f9dc iopl=0 nv up ei pl nz na po cy
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000203
ntdll!LdrpValidateUserCallTargetBitMapCheck:
77408beb 8b1482 mov edx,dword ptr [edx+eax*4] ds:002b:009d644c=10100444

我们看看记录的目录,共有三个文件,.run是trace文件,idx是索引文件,索引文件可以让我们更快地访问跟踪信息。假如我们只有.run文件,也是可以的,当WinDbg Preview打开跟踪文件(.run)时,索引文件也会自动创建。

利用别人的跟踪文件调试

这是参考文章的作者给的文件,一个.run文件就592M了,但是可以免除搭建环境,1个G甚至8个G我都能接受

这个漏洞是Adobe Acrobat Reader DC for Windows - Double Free due to Malformed JP2 Stream(CVE-2019-8044),POC可以在下面下载

https://www.exploit-db.com/exploits/47279

我就不下载POC复现了,直接用作者的跟踪文件分析,载入run文件后,直接g,触发崩溃

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Time Travel Position: 224FB2:1
eax=000d0004 ebx=00000000 ecx=ffffd8f0 edx=770d2330 esi=00003a98 edi=00000000
eip=67ce7001 esp=010cc25c ebp=010cc2a8 iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
67ce7001 0970ce or dword ptr [eax-32h],esi ds:002b:000cffd2=????????
0:001> kv
# ChildEBP RetAddr Args to Child
WARNING: Frame IP not in any known module. Following frames may be wrong.
00 010cc258 770bdc2c 770ffa22 000006d4 00000000 0x67ce7001
01 010cc25c 770ffa22 000006d4 00000000 010cc290 ntdll!NtWaitForSingleObject+0xc (FPO: [3,0,0])
02 010cc2a8 770ff802 010cce6c 00000568 00000000 ntdll!WaitForWerSvc+0x77 (FPO: [Non-Fpo])
03 010cc338 770fed66 00000000 000002dc 00000000 ntdll!SendMessageToWERService+0x5d (FPO: [Non-Fpo])
04 010cce28 770ff3b1 010cd25c 00000004 00000000 ntdll!ReportExceptionInternal+0xde (FPO: [4,695,4])
05 010cd288 770fee0a 00000000 00000000 00000000 ntdll!RtlReportExceptionHelper+0x29d (FPO: [Non-Fpo])
06 010cd2ac 77129865 010cd424 010cd474 00000000 ntdll!RtlReportException+0x6a (FPO: [3,3,4])
07 010cd2bc 770c20b0 010cd964 00000001 fffffffe ntdll!RtlReportCriticalFailure+0xad (FPO: [SEH])
08 010cd2d0 770c19c0 00000000 00000000 00000000 ntdll!_EH4_CallFilterFunc+0x12 (FPO: [Uses EBP] [0,0,4])
09 010cd2fc 770c5e00 771632d4 770bfbd0 010cd424 ntdll!_except_handler4_common+0x80 (FPO: [Non-Fpo])
0a 010cd31c 770d23b2 010cd424 010cd954 010cd474 ntdll!_except_handler4+0x20 (FPO: [Non-Fpo])
0b 010cd340 770d2384 010cd424 010cd954 010cd474 ntdll!ExecuteHandler2+0x26
0c 010cd40c 770bff1f 010cd424 010cd474 010cd424 ntdll!ExecuteHandler+0x24
0d 010cd964 00000000 00000001 00000002 7712b763 ntdll!KiUserExceptionDispatcher+0xf (FPO: [2,0,0]) (CONTEXT @ ffffffff)

可以看到这里面看不到什么有用的东西,都是windows的异常处理函数相关的,而且我们通过信息已经知道这个漏洞是double free了,可能是free的时候崩溃的,我们需要向上回溯

通过不断点击step out back,或者命令g-u去不断返回,但是我们到ntdll!KiUserExceptionDispatcher+0xf的时候再返回,就变成载入时的状态,所以到这一步我们应该点击step over back,或者命令p-,多step over back几次即可

最终可以执行下面命令回到真正触发崩溃的地方

1
g-u;g-u;g-u;g-u;g-u;g-u;g-u;g-u;g-u;g-u;g-u;g-u;g-u;p-;p-;p-;p-;p-;p-;

再看下此时的栈,是MSVCR120!free之后调用ntdll!RtlFreeHeap失败,最终进入ntdll!RtlpLogHeapFailure处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
0:001> kb
# ChildEBP RetAddr Args to Child
WARNING: Frame IP not in any known module. Following frames may be wrong.
00 010cd5e0 770bf13c 770d2595 010cd8f8 010cd5f8 0x67ce7000
01 010cd5e4 770d2595 010cd8f8 010cd5f8 00000001 ntdll!NtRaiseException+0xc
02 010cd8c8 77129841 010cd8f8 3a9cf7ad 1fb1c848 ntdll!RtlRaiseException+0x35
03 010cd964 7712cfe2 00000001 00000002 7712b763 ntdll!RtlReportCriticalFailure+0x89
04 010cd970 7712b763 01670000 00000002 010cd9b0 ntdll!RtlpReportHeapFailure+0x32
05 010cd980 770d16cf 3a9cf779 01670000 1fb1c848 ntdll!RtlpHeapHandleError+0x1c
06 010cd9b0 770e23be 1fb1c848 00000000 00000000 ntdll!RtlpLogHeapFailure+0x9f
07 010cd9e4 6b1becfa 01670000 00000000 1fb1c850 ntdll!RtlFreeHeap+0x4abce
08 010cd9f8 6a18b2a7 1fb1c850 277326dc 010cdb5c MSVCR120!free+0x1a [f:\dd\vctools\crt\crtw32\heap\free.c @ 51]
09 010cdb0c 6a17bc96 010cdb7c 00000001 00000b20 AcroRd32!CTJPEGTiledContentWriter::operator=+0x12c83
0a 010cdcd4 6a179c26 00000000 00000000 00000000 AcroRd32!CTJPEGTiledContentWriter::operator=+0x3672
0b 010cdd08 6a171033 1ff1e030 074eaf44 074eaf60 AcroRd32!CTJPEGTiledContentWriter::operator=+0x1602
0c 010cdd1c 6a1654a7 1ff1e030 000033f8 07637cd8 AcroRd32!AX_PDXlateToHostEx+0x271448
0d 010cddc4 69c7c595 074eaf44 00000001 078438e0 AcroRd32!AX_PDXlateToHostEx+0x2658bc
0e 010cdde0 69c7c4a9 20a54028 00000001 0013d690 AcroRd32!CTJPEGWriter::CTJPEGWriter+0x22d4d
0f 010cde00 69c119d7 010cde20 20a54028 0013d690 AcroRd32!CTJPEGWriter::CTJPEGWriter+0x22c61
10 010cde28 69c1198d 20a54028 00000001 0013d690 AcroRd32!AcroWinBrowserMain+0x19eb3
11 010cde3c 69cb0c16 20a54028 00000001 0013d690 AcroRd32!AcroWinBrowserMain+0x19e69
12 010cde54 69d8d21a 20a54028 00000001 0013d690 AcroRd32!CTJPEGWriter::CTJPEGWriter+0x573ce
13 010cdea8 6a0ee398 00000000 00000e44 076a1e54 AcroRd32!CTJPEGDecoderHasMoreTiles+0xf4a
14 010cdf20 69ff0017 010cdf40 010cdf50 277322b4 AcroRd32!AX_PDXlateToHostEx+0x1ee7ad
15 010cdf64 6b369939 07557880 010cdf88 26c94051 AcroRd32!AX_PDXlateToHostEx+0xf042c
16 010ce010 6b5f6028 075578d8 010ce024 00000000 AGM!AGMGetVersion+0x14263
17 010ce028 6b2fb9af 010ce0cc 26c97f11 00112015 AGM!AGMGetVersion+0x2a0952
18 00000000 00000000 00000000 00000000 00000000 AGM!AGMInitialize+0x33153

我们看看什么导致checkfail了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
Time Travel Position: 222B02:6F
eax=6ae3fb4c ebx=1fb1c850 ecx=00000008 edx=01670000 esi=1fb1c848 edi=01670000
eip=770e23b9 esp=010cd9b8 ebp=010cd9e4 iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
ntdll!RtlFreeHeap+0x4abc9:
770e23b9 e872f2feff call ntdll!RtlpLogHeapFailure (770d1630)
0:001> t-
Time Travel Position: 222B02:6E

**** WARNING loaded *kernel* extension dll for usermode

eax=6ae3fb4c ebx=1fb1c850 ecx=1fb1c850 edx=01670000 esi=1fb1c848 edi=01670000
eip=770e23b4 esp=010cd9b8 ebp=010cd9e4 iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
ntdll!RtlFreeHeap+0x4abc4:
770e23b4 b908000000 mov ecx,8
0:001> t-
Time Travel Position: 222B02:6D

**** WARNING loaded *kernel* extension dll for usermode

eax=6ae3fb4c ebx=1fb1c850 ecx=1fb1c850 edx=00000000 esi=1fb1c848 edi=01670000
eip=770e23b2 esp=010cd9b8 ebp=010cd9e4 iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
ntdll!RtlFreeHeap+0x4abc2:
770e23b2 8bd7 mov edx,edi
0:001> t-
Time Travel Position: 222B02:6C

**** WARNING loaded *kernel* extension dll for usermode

eax=6ae3fb4c ebx=1fb1c850 ecx=1fb1c850 edx=00000000 esi=1fb1c848 edi=01670000
eip=770e23b1 esp=010cd9bc ebp=010cd9e4 iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
ntdll!RtlFreeHeap+0x4abc1:
770e23b1 56 push esi
0:001> t-
Time Travel Position: 222B02:6B

**** WARNING loaded *kernel* extension dll for usermode

eax=6ae3fb4c ebx=1fb1c850 ecx=1fb1c850 edx=00000000 esi=1fb1c848 edi=01670000
eip=770e23af esp=010cd9c0 ebp=010cd9e4 iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
ntdll!RtlFreeHeap+0x4abbf:
770e23af 6a00 push 0
0:001> t-
Time Travel Position: 222B02:6A

**** WARNING loaded *kernel* extension dll for usermode

eax=6ae3fb4c ebx=1fb1c850 ecx=1fb1c850 edx=00000000 esi=1fb1c848 edi=01670000
eip=770e23ad esp=010cd9c4 ebp=010cd9e4 iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
ntdll!RtlFreeHeap+0x4abbd:
770e23ad 6a00 push 0
0:001> t-
Time Travel Position: 222B02:69

**** WARNING loaded *kernel* extension dll for usermode

eax=6ae3fb4c ebx=1fb1c850 ecx=1fb1c850 edx=00000000 esi=1fb1c848 edi=01670000
eip=770e23ab esp=010cd9c8 ebp=010cd9e4 iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
ntdll!RtlFreeHeap+0x4abbb:
770e23ab 6a00 push 0
0:001> t-
Time Travel Position: 222B02:68

**** WARNING loaded *kernel* extension dll for usermode

eax=6ae3fb4c ebx=1fb1c850 ecx=1fb1c850 edx=00000000 esi=1fb1c848 edi=01670000
eip=77097855 esp=010cd9c8 ebp=010cd9e4 iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
ntdll!RtlFreeHeap+0x65:
77097855 0f8450ab0400 je ntdll!RtlFreeHeap+0x4abbb (770e23ab) [br=1]
0:001> t-
Time Travel Position: 222B02:67

**** WARNING loaded *kernel* extension dll for usermode

eax=6ae3fb4c ebx=1fb1c850 ecx=1fb1c850 edx=00000000 esi=1fb1c848 edi=01670000
eip=77097851 esp=010cd9c8 ebp=010cd9e4 iopl=0 ov up ei pl nz ac pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000a16
ntdll!RtlFreeHeap+0x61:
77097851 f646073f test byte ptr [esi+7],3Fh ds:002b:1fb1c84f=80

原来是这个77097851 f646073f test byte ptr [esi+7],3Fh ds:002b:1fb1c84f=80

这个地址肯定被改写了才导致检查是吧,所以我们可以对这个地址下一个写入断点,之后往回走,g-就行,实在太方便了

1
2
ba w1 1fb1c84f
g-

由于这个断下来会停在写入的下一个指令,所以还要p-一下

1
2
3
4
5
6
7
8
9
10
0:001> p-
Time Travel Position: 222B02:B

**** WARNING loaded *kernel* extension dll for usermode

eax=0317022d ebx=1fb1c848 ecx=8317022d edx=0317022d esi=0317022d edi=078410c0
eip=77097953 esp=010cd990 ebp=010cd9bc iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
ntdll!RtlpLowFragHeapFree+0x93:
77097953 c6430780 mov byte ptr [ebx+7],80h ds:002b:1fb1c84f=88

这时再看一下栈,可以看到MSVCR120!free(void * pBlock = 0x1fb1c850)+0x1a,是free(0x1fb1c850)后导致的写入,而且这个栈跟上面的有所区别,所以这应该是第一次free,写入了0x80后,导致第二次free失败了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
0:001> kp
# ChildEBP RetAddr
00 010cd9bc 7709787d ntdll!RtlpLowFragHeapFree+0x93
01 010cd9e4 6b1becfa ntdll!RtlFreeHeap+0x8d
02 010cd9f8 6a18b296 MSVCR120!free(void * pBlock = 0x1fb1c850)+0x1a [f:\dd\vctools\crt\crtw32\heap\free.c @ 51]
WARNING: Stack unwind information not available. Following frames may be wrong.
03 010cdb0c 6a17bc96 AcroRd32!CTJPEGTiledContentWriter::operator=+0x12c72
04 010cdcd4 6a179c26 AcroRd32!CTJPEGTiledContentWriter::operator=+0x3672
05 010cdd08 6a171033 AcroRd32!CTJPEGTiledContentWriter::operator=+0x1602
06 010cdd1c 6a1654a7 AcroRd32!AX_PDXlateToHostEx+0x271448
07 010cddc4 69c7c595 AcroRd32!AX_PDXlateToHostEx+0x2658bc
08 010cdde0 69c7c4a9 AcroRd32!CTJPEGWriter::CTJPEGWriter+0x22d4d
09 010cde00 69c119d7 AcroRd32!CTJPEGWriter::CTJPEGWriter+0x22c61
0a 010cde28 69c1198d AcroRd32!AcroWinBrowserMain+0x19eb3
0b 010cde3c 69cb0c16 AcroRd32!AcroWinBrowserMain+0x19e69
0c 010cde54 69d8d21a AcroRd32!CTJPEGWriter::CTJPEGWriter+0x573ce
0d 010cdea8 6a0ee398 AcroRd32!CTJPEGDecoderHasMoreTiles+0xf4a
0e 010cdf20 69ff0017 AcroRd32!AX_PDXlateToHostEx+0x1ee7ad
0f 010cdf64 6b369939 AcroRd32!AX_PDXlateToHostEx+0xf042c
10 010ce010 6b5f6028 AGM!AGMGetVersion+0x14263
11 010ce028 6b2fb9af AGM!AGMGetVersion+0x2a0952
12 00000000 00000000 AGM!AGMInitialize+0x33153

参考文章的作者还给出了TTD的一个牛逼的命令,可以看到MSVCR120!malloc什么时候返回0x1fb1c850
注:下面中括号的四个可能会变

1
2
3
4
5
6
0:001> dx -r1 @$cursession.TTD.Calls("MSVCR120!malloc").Where(c => c.ReturnValue == (void *)0x1fb1c850)
@$cursession.TTD.Calls("MSVCR120!malloc").Where(c => c.ReturnValue == (void *)0x1fb1c850)
[0x231fe]
[0x3991b]
[0x3c926]
[0x3e405]

之后可以在后面加个中括号去访问对应的那个状态,可以看到他的时间点去判断是在free之前malloc的还是之后(下面的TimeStart)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
0:001> dx -r1 @$cursession.TTD.Calls("MSVCR120!malloc").Where(c => c.ReturnValue == (void *)0x1fb1c850)[0x231fe]
@$cursession.TTD.Calls("MSVCR120!malloc").Where(c => c.ReturnValue == (void *)0x1fb1c850)[0x231fe]
EventType : 0x0
ThreadId : 0x146c
UniqueThreadId : 0x8
TimeStart : 20FB5D:162 [Translate Position]
SystemTimeStart : Unexpected failure to dereference object
TimeEnd : 20FB5E:90 [Translate Position]
SystemTimeEnd : Unexpected failure to dereference object
Function : MSVCR120!malloc
FunctionAddress : 0x6b1bed30
ReturnAddress : 0x69bf3042
ReturnValue : 0x1fb1c850 [Type: void *]
Parameters

或者直接点击那是个中括号的值(点击的话中括号的会变成十进制的)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
0:001> dx -r1 @$cursession.TTD.Calls("MSVCR120!malloc").Where(c => c.ReturnValue == (void *)0x1fb1c850)[143870]
@$cursession.TTD.Calls("MSVCR120!malloc").Where(c => c.ReturnValue == (void *)0x1fb1c850)[143870]
EventType : 0x0
ThreadId : 0x146c
UniqueThreadId : 0x8
TimeStart : 20FB5D:162 [Translate Position]
SystemTimeStart : Unexpected failure to dereference object
TimeEnd : 20FB5E:90 [Translate Position]
SystemTimeEnd : Unexpected failure to dereference object
Function : MSVCR120!malloc
FunctionAddress : 0x6b1bed30
ReturnAddress : 0x69bf3042
ReturnValue : 0x1fb1c850 [Type: void *]
Parameters
0:001> dx -r1 @$cursession.TTD.Calls("MSVCR120!malloc").Where(c => c.ReturnValue == (void *)0x1fb1c850)[235803]
@$cursession.TTD.Calls("MSVCR120!malloc").Where(c => c.ReturnValue == (void *)0x1fb1c850)[235803]
EventType : 0x0
ThreadId : 0x13a0
UniqueThreadId : 0x3
TimeStart : 1EA482:1C1 [Translate Position]
SystemTimeStart : Unexpected failure to dereference object
TimeEnd : 1EA483:90 [Translate Position]
SystemTimeEnd : Unexpected failure to dereference object
Function : MSVCR120!malloc
FunctionAddress : 0x6b1bed30
ReturnAddress : 0x68b49911
ReturnValue : 0x1fb1c850 [Type: void *]
Parameters
0:001> dx -r1 @$cursession.TTD.Calls("MSVCR120!malloc").Where(c => c.ReturnValue == (void *)0x1fb1c850)[248102]
@$cursession.TTD.Calls("MSVCR120!malloc").Where(c => c.ReturnValue == (void *)0x1fb1c850)[248102]
EventType : 0x0
ThreadId : 0x13a0
UniqueThreadId : 0x3
TimeStart : 1F94B3:D6 [Translate Position]
SystemTimeStart : Unexpected failure to dereference object
TimeEnd : 1F94B4:90 [Translate Position]
SystemTimeEnd : Unexpected failure to dereference object
Function : MSVCR120!malloc
FunctionAddress : 0x6b1bed30
ReturnAddress : 0x68b49911
ReturnValue : 0x1fb1c850 [Type: void *]
Parameters
0:001> dx -r1 @$cursession.TTD.Calls("MSVCR120!malloc").Where(c => c.ReturnValue == (void *)0x1fb1c850)[254981]
@$cursession.TTD.Calls("MSVCR120!malloc").Where(c => c.ReturnValue == (void *)0x1fb1c850)[254981]
EventType : 0x0
ThreadId : 0x13a0
UniqueThreadId : 0x3
TimeStart : 2201C5:62 [Translate Position]
SystemTimeStart : Unexpected failure to dereference object
TimeEnd : 2201C6:90 [Translate Position]
SystemTimeEnd : Unexpected failure to dereference object
Function : MSVCR120!malloc
FunctionAddress : 0x6b1bed30
ReturnAddress : 0x6a17cd10
ReturnValue : 0x1fb1c850 [Type: void *]
Parameters

写入0x80的时间是Time Travel Position: 222B02:B(第一次free),所以malloc应该在他前面且最近的一次

上面四个分别是下面的,所以最近的应该是最后一个

1
2
3
4
5
6
7
TimeStart        : 20FB5D:162 [Translate Position]

TimeStart : 1EA482:1C1 [Translate Position]

TimeStart : 1F94B3:D6 [Translate Position]

TimeStart : 2201C5:62 [Translate Positio

跟参考文章作者得出的一样,只不过那个中括号的排序可能有所差异

感觉这样还没有条件记录断点方便,但是还是挺清晰的

跟踪free

到上面写入0x80这,我们已经在第一次free的里面了

向上回溯,到第一次调用free的地方(AcroRd32!AcroWinBrowserMain+0x2593里面会调用MSVCR120!free)

1
2
3
4
5
6
7
8
9
10
0:001> p-
Time Travel Position: 222B01:43

**** WARNING loaded *kernel* extension dll for usermode

eax=1fb1c850 ebx=00000000 ecx=1fb1c7f0 edx=00000000 esi=1fb1c400 edi=00000000
eip=6a18b291 esp=010cda00 ebp=010cdb0c iopl=0 nv up ei pl nz na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000206
AcroRd32!CTJPEGTiledContentWriter::operator=+0x12c6d:
6a18b291 e821eea6ff call AcroRd32!AcroWinBrowserMain+0x2593 (69bfa0b7)

而我们看看现在代码上下,发现两次调用了AcroRd32!AcroWinBrowserMain+0x2593

1
2
3
4
5
6
7
8
9
10
11
6a18b286 8b8568ffffff mov     eax, dword ptr [ebp-98h]
6a18b28c 85c0 test eax, eax
6a18b28e 7407 je AcroRd32!CTJPEGTiledContentWriter::operator=+0x12c73 (6a18b297)
6a18b290 50 push eax
6a18b291 e821eea6ff call AcroRd32!AcroWinBrowserMain+0x2593 (69bfa0b7)
6a18b296 59 pop ecx
6a18b297 8b8570ffffff mov eax, dword ptr [ebp-90h]
6a18b29d 85c0 test eax, eax
6a18b29f 7407 je AcroRd32!CTJPEGTiledContentWriter::operator=+0x12c84 (6a18b2a8)
6a18b2a1 50 push eax
6a18b2a2 e810eea6ff call AcroRd32!AcroWinBrowserMain+0x2593 (69bfa0b7)

我们向下执行(记得将写入断点禁用),看看是不是

1
2
3
4
5
6
7
8
9
10
11
6a18b286 8b8568ffffff mov     eax, dword ptr [ebp-98h]
6a18b28c 85c0 test eax, eax
6a18b28e 7407 je AcroRd32!CTJPEGTiledContentWriter::operator=+0x12c73 (6a18b297)
6a18b290 50 push eax
6a18b291 e821eea6ff call AcroRd32!AcroWinBrowserMain+0x2593 (69bfa0b7)
6a18b296 59 pop ecx
6a18b297 8b8570ffffff mov eax, dword ptr [ebp-90h] ss:002b:010cda7c=1fb1c850
6a18b29d 85c0 test eax, eax
6a18b29f 7407 je AcroRd32!CTJPEGTiledContentWriter::operator=+0x12c84 (6a18b2a8)
6a18b2a1 50 push eax
6a18b2a2 e810eea6ff call AcroRd32!AcroWinBrowserMain+0x2593 (69bfa0b7)

可以看到[ebp-90h]里面存的还是1fb1c850,那就明显free了两次了

看下内存更清晰

1
2
3
4
0:001> dd ebp-98 l4
010cda74 1fb1c850 00000000 1fb1c850 00000018
0:001> dd ebp-90 l4
010cda7c 1fb1c850 00000018 00000000 00000000

最终在第二个 call AcroRd32!AcroWinBrowserMain+0x2593 (69bfa0b7) 里面崩溃,确实free两次了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
0:001> p
Time Travel Position: 222B02:3A

**** WARNING loaded *kernel* extension dll for usermode

eax=1fb1c850 ebx=00000000 ecx=1fb1c850 edx=00000000 esi=1fb1c400 edi=00000000
eip=6a18b2a2 esp=010cda00 ebp=010cdb0c iopl=0 nv up ei pl nz na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000206
AcroRd32!CTJPEGTiledContentWriter::operator=+0x12c7e:
6a18b2a2 e810eea6ff call AcroRd32!AcroWinBrowserMain+0x2593 (69bfa0b7)
0:001> p
(2dc.13a0): Unknown exception - code c0000374 (first/second chance not available)

**** WARNING loaded *kernel* extension dll for usermode

TTD: End of trace reached.
(2dc.13a0): Break instruction exception - code 80000003 (first/second chance not available)

**** WARNING loaded *kernel* extension dll for usermode

Time Travel Position: 224FB2:1
eax=000d0004 ebx=00000000 ecx=ffffd8f0 edx=770d2330 esi=00003a98 edi=00000000
eip=67ce7001 esp=010cc25c ebp=010cc2a8 iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
67ce7001 0970ce or dword ptr [eax-32h],esi ds:002b:000cffd2=????????

那么这个[ebp-98h]和[ebp-90h]从哪里来的呢,由于这个是4字节的,我下一个4字节的写入断点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
0:001> ba w4 010cda74
0:001> ba w4 010cda7c
0:001> g-
Breakpoint 4 hit

**** WARNING loaded *kernel* extension dll for usermode

Time Travel Position: 222B00:1AD3
eax=1fb1c850 ebx=00000000 ecx=016afde0 edx=00000003 esi=1fb1c700 edi=00000000
eip=6a18ac78 esp=010cda04 ebp=010cdb0c iopl=0 nv up ei pl nz ac po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000212
AcroRd32!CTJPEGTiledContentWriter::operator=+0x12654:
6a18ac78 8d45a8 lea eax,[ebp-58h]
0:001> p-
Time Travel Position: 222B00:1AD2

**** WARNING loaded *kernel* extension dll for usermode

eax=1fb1c850 ebx=00000000 ecx=016afde0 edx=00000003 esi=1fb1c700 edi=00000000
eip=6a18ac72 esp=010cda04 ebp=010cdb0c iopl=0 nv up ei pl nz ac po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000212
AcroRd32!CTJPEGTiledContentWriter::operator=+0x1264e:
6a18ac72 898570ffffff mov dword ptr [ebp-90h],eax ss:002b:010cda7c=0000077f
0:001> g-
Breakpoint 3 hit

**** WARNING loaded *kernel* extension dll for usermode

Time Travel Position: 222B00:1AA4
eax=1fb1c850 ebx=00000000 ecx=016afde0 edx=00000003 esi=1fb1c700 edi=00000000
eip=6a18ac5f esp=010cd9cc ebp=010cdb0c iopl=0 nv up ei ng nz na pe cy
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000287
AcroRd32!CTJPEGTiledContentWriter::operator=+0x1263b:
6a18ac5f 6a0f push 0Fh
0:001> p-
Time Travel Position: 222B00:1AA3

**** WARNING loaded *kernel* extension dll for usermode

eax=1fb1c850 ebx=00000000 ecx=016afde0 edx=00000003 esi=1fb1c700 edi=00000000
eip=6a18ac59 esp=010cd9cc ebp=010cdb0c iopl=0 nv up ei ng nz na pe cy
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000287
AcroRd32!CTJPEGTiledContentWriter::operator=+0x12635:
6a18ac59 898568ffffff mov dword ptr [ebp-98h],eax ss:002b:010cda74=1ff69498

这两个代码很接近,我们看看上下文

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
6a18ac3f 56           push    esi
6a18ac40 53 push ebx
6a18ac41 6a0f push 0Fh
6a18ac43 89855cffffff mov dword ptr [ebp-0A4h], eax
6a18ac49 8d45a8 lea eax, [ebp-58h]
6a18ac4c 6a0e push 0Eh
6a18ac4e 50 push eax
6a18ac4f ff75e4 push dword ptr [ebp-1Ch]
6a18ac52 e88e060000 call AcroRd32!CTJPEGTiledContentWriter::operator=+0x12cc1 (6a18b2e5)
6a18ac57 56 push esi
6a18ac58 53 push ebx
6a18ac59 898568ffffff mov dword ptr [ebp-98h], eax ss:002b:010cda74=1ff69498
6a18ac5f 6a0f push 0Fh
6a18ac61 6a0e push 0Eh
6a18ac63 8d45a8 lea eax, [ebp-58h]
6a18ac66 50 push eax
6a18ac67 ff75e5 push dword ptr [ebp-1Bh]
6a18ac6a e876060000 call AcroRd32!CTJPEGTiledContentWriter::operator=+0x12cc1 (6a18b2e5)
6a18ac6f 83c448 add esp, 48h
6a18ac72 898570ffffff mov dword ptr [ebp-90h], eax

这个函数其实是GetMemoryBlock函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
undefined4
GetMemoryBlock(undefined4 memory_block_type,int *param_2,byte offsetVal1,byte offsetVal2,
undefined4 offsetVal3,int param_6)

{
undefined4 retVal;
int memory_block_base;
byte offset;
code *pcVar1;

if ((char)memory_block_type == '\x03') {
if ((param_2 == (int *)0x0) || (param_6 == 0)) {
exception:
CallThrowException(0x40000003,0);
memory_block_type = 0;
_CxxThrowException(&memory_block_type,0x7472e75c);
pcVar1 = (code *)swi(3);
retVal = (*pcVar1)();
return retVal;
}
*param_2 = *param_2 + 1;
retVal = RetrieveMemoryBlock(param_6,*param_2 + -1);
}
else {
offset = offsetVal1;
if (((char)memory_block_type != '\0') &&
(offset = offsetVal2, (char)memory_block_type != '\x01')) {
if ((char)memory_block_type != '\x02') goto exception;
offset = (byte)offsetVal3;
}
if (offset == 0) goto exception;
memory_block_base = (*_TlsGetValueStub)(_dwTlsIndexForMemoryBlockBase);
retVal = *(undefined4 *)(memory_block_base + 0x20 + (uint)offset * 4);
}
return retVal;
}

我们看看两次调用的6个参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
eax=010cdab4 ebx=00000000 ecx=1fb1c700 edx=00000003 esi=1fb1c700 edi=00000000
eip=6a18ac52 esp=010cd9d4 ebp=010cdb0c iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
AcroRd32!CTJPEGTiledContentWriter::operator=+0x1262e:
6a18ac52 e88e060000 call AcroRd32!CTJPEGTiledContentWriter::operator=+0x12cc1 (6a18b2e5)
0:001> dds esp l6
010cd9d4 01000000
010cd9d8 010cdab4
010cd9dc 0000000e
010cd9e0 0000000f
010cd9e4 00000000
010cd9e8 1fb1c700
eax=010cdab4 ebx=00000000 ecx=016afde0 edx=00000003 esi=1fb1c700 edi=00000000
eip=6a18ac6a esp=010cd9bc ebp=010cdb0c iopl=0 nv up ei ng nz na pe cy
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000287
AcroRd32!CTJPEGTiledContentWriter::operator=+0x12646:
6a18ac6a e876060000 call AcroRd32!CTJPEGTiledContentWriter::operator=+0x12cc1 (6a18b2e5)
0:001> dds esp l6
010cd9bc 00010000
010cd9c0 010cdab4
010cd9c4 0000000e
010cd9c8 0000000f
010cd9cc 00000000
010cd9d0 1fb1c700

可以看到两次调用,只是第一个参数不一样,第一次是0x01000000,第二次是0x00010000,但是返回结果是一样的,而函数GetMemoryBlock里面是将memory_block_type强制转为char进行处理的,所以他们都是0x00,导致返回结果一样。

执行的是else部分代码

1
2
3
4
5
6
7
8
9
10
11
else {
offset = offsetVal1;
if (((char)memory_block_type != '\0') &&
(offset = offsetVal2, (char)memory_block_type != '\x01')) {
if ((char)memory_block_type != '\x02') goto exception;
offset = (byte)offsetVal3;
}
if (offset == 0) goto exception;
memory_block_base = (*_TlsGetValueStub)(_dwTlsIndexForMemoryBlockBase);
retVal = *(undefined4 *)(memory_block_base + 0x20 + (uint)offset * 4);
}

最终offset = offsetVal1 = 0x0000000e
retVal = *(memory_block_base + 0x20 + (uint)offset * 4 = 0x016afde0 + 0x20 + 0x0000000e * 4) = *(0x16afe38)

我们看看这个地址的值,的确是0x1fb1c850

1
2
0:001>  dd 0x16afe38 l1
016afe38 1fb1c850

跟踪0x00010000来源

1
2
3
4
5
eax=010cdab4 ebx=00000000 ecx=016afde0 edx=00000003 esi=1fb1c700 edi=00000000
eip=6a18ac67 esp=010cd9c0 ebp=010cdb0c iopl=0 nv up ei ng nz na pe cy
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000287
AcroRd32!CTJPEGTiledContentWriter::operator=+0x12643:
6a18ac67 ff75e5 push dword ptr [ebp-1Bh] ss:002b:010cdaf1=00010000

对 [ebp-1Bh]下吸入断点

1
2
3
4
5
6
7
8
9
10
11
12
0:001> ba w1 010cdaf1
0:001> g-
Breakpoint 5 hit

**** WARNING loaded *kernel* extension dll for usermode

Time Travel Position: 222B00:19AE
eax=00000000 ebx=1fbad818 ecx=00000002 edx=010cdb7c esi=010cdb54 edi=010cdaf4
eip=6a18ab57 esp=010cda04 ebp=010cdb0c iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
AcroRd32!CTJPEGTiledContentWriter::operator=+0x12533:
6a18ab57 f3a5 rep movs dword ptr es:[edi],dword ptr [esi]

这里是010cdb54指向的值吸入010cdaf4,那么010cdaf1就来源于010cdb51,看了下确实是0x00010000

1
2
0:001> dd 010cdb51 l1
010cdb51 00010000

继续不断下硬件写入断点,跟踪010cdb51,来源于0x010cdbd1,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
0:001> ba w1 010cdb51
0:001> g-
Breakpoint 6 hit

**** WARNING loaded *kernel* extension dll for usermode

Time Travel Position: 222B00:197C
eax=010cdb7c ebx=1fbad818 ecx=00000002 edx=00000003 esi=010cdbd4 edi=010cdb54
eip=6a17bc8e esp=010cdb18 ebp=010cdcd4 iopl=0 nv up ei pl nz na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000206
AcroRd32!CTJPEGTiledContentWriter::operator=+0x366a:
6a17bc8e f3a5 rep movs dword ptr es:[edi],dword ptr [esi]
0:001> ba w1 010cdbd1
0:001> g-
Breakpoint 7 hit

**** WARNING loaded *kernel* extension dll for usermode

Time Travel Position: 222AAF:140
eax=1fb1c700 ebx=1fbad818 ecx=00000502 edx=00000666 esi=0000000f edi=00000001
eip=6a17b868 esp=010cdb6c ebp=010cdcd4 iopl=0 nv up ei pl nz na po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000202
AcroRd32!CTJPEGTiledContentWriter::operator=+0x3244:
6a17b868 8a437e mov al,byte ptr [ebx+7Eh] ds:002b:1fbad896=00

这个往上看看,写入的00来源于0x1fbad895

1
2
3
6a17b85f 8a437d         mov     al, byte ptr [ebx+7Dh]      ds:002b:1fbad895=00
6a17b862 8885fdfeffff mov byte ptr [ebp-103h], al
6a17b868 8a437e mov al, byte ptr [ebx+7Eh]

后面有两个字节来源于别处,而且都是0

1
2
3
4
5
a17b86b 8885fefeffff   mov     byte ptr [ebp-102h], al
6a17b871 668b8380000000 mov ax, word ptr [ebx+80h]
6a17b878 899538ffffff mov dword ptr [ebp-0C8h], edx
6a17b87e 8995d8feffff mov dword ptr [ebp-128h], edx
6a17b884 66898500ffffff mov word ptr [ebp-100h], ax

只有ebp-101没被修改,而这里本来就是01了

1
2
0:001> db ebp-101 l1
010cdbd3 01

而我们关注的是最低字节,继续看看1fbad895的写入

1
2
3
4
5
6
7
8
9
10
11
12
0:001> ba w1 1fbad895
0:001> g-
Breakpoint 8 hit

**** WARNING loaded *kernel* extension dll for usermode

Time Travel Position: 222AAB:7F5
eax=00000000 ebx=00000003 ecx=000000ff edx=0763beae esi=1fbad818 edi=1fb39030
eip=6a17be59 esp=010cdb60 ebp=010cdcd4 iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
AcroRd32!CTJPEGTiledContentWriter::operator=+0x3835:
6a17be59 8bc1 mov eax,ecx

向上看

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
6a17be18 e809d5ffff     call    AcroRd32!CTJPEGTiledContentWriter::operator=+0xd02 (6a179326)
6a17be1d 0fb7c8 movzx ecx, ax
---------------------------------------- 下面的中间的代码可以忽略了,就是上面call返回值给到ecx
6a17be20 8ac1 mov al, cl
6a17be22 22c3 and al, bl
6a17be24 884678 mov byte ptr [esi+78h], al
6a17be27 8ac1 mov al, cl
6a17be29 c0e802 shr al, 2
6a17be2c 22c3 and al, bl
6a17be2e 884679 mov byte ptr [esi+79h], al
6a17be31 8ac1 mov al, cl
6a17be33 c0e804 shr al, 4
6a17be36 22c3 and al, bl
6a17be38 88467a mov byte ptr [esi+7Ah], al
6a17be3b 8ac1 mov al, cl
6a17be3d c0e806 shr al, 6
6a17be40 22c3 and al, bl
6a17be42 88467b mov byte ptr [esi+7Bh], al
6a17be45 8bc1 mov eax, ecx
6a17be47 c1e808 shr eax, 8
6a17be4a 22c3 and al, bl
6a17be4c 88467c mov byte ptr [esi+7Ch], al
----------------------------------------ecx给到eax做些运算写入1fbad895
6a17be4f 8bc1 mov eax, ecx
6a17be51 c1e80a shr eax, 0Ah
6a17be54 22c3 and al, bl
6a17be56 88467d mov byte ptr [esi+7Dh], al
6a17be59 8bc1 mov eax, ecx

上面说明分析看出来源于call AcroRd32!CTJPEGTiledContentWriter::operator=+0xd02 (6a179326)的返回值,跟进去看看,分析可以看出实际来源于0x0763beac

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
6a179358 0fb608     movzx   ecx, byte ptr [eax]         ds:002b:0763beac=00
6a17935b 8d5001 lea edx, [eax+1]
6a17935e 8917 mov dword ptr [edi], edx
6a179360 83fe01 cmp esi, 1
6a179363 760f jbe AcroRd32!CTJPEGTiledContentWriter::operator=+0xd50 (6a179374)
6a179365 4e dec esi
6a179366 0fb602 movzx eax, byte ptr [edx] ;eax来源于edx,即上面6a17935b的[eax+1]
6a179369 c1e108 shl ecx, 8
6a17936c 03c8 add ecx, eax ;ecx来源于跟eax运算,ecx又来源于6a179358的[eax]
6a17936e 42 inc edx
6a17936f 8917 mov dword ptr [edi], edx
6a179371 4e dec esi
6a179372 75f2 jne AcroRd32!CTJPEGTiledContentWriter::operator=+0xd42 (6a179366)
6a179374 8bc1 mov eax, ecx ;eax来源于ecx
6a179376 eb03 jmp AcroRd32!CTJPEGTiledContentWriter::operator=+0xd57 (6a17937b) ;跳到6a17937b
----下面两行没执行
6a179378 6a0a push 0Ah
6a17937a 58 pop eax

6a17937b 5f pop edi
6a17937c 5e pop esi
6a17937d 5d pop ebp
6a17937e c20400 ret 4

看看里面

1
2
3
4
5
6
7
8
9
0:001> db 0763beac
0763beac 00 ff 00 00 05 63 20 00-77 65 55 23 00 00 00 00 .....c .weU#....
0763bebc 00 00 00 00 00 00 43 4e-70 39 0f 76 71 19 85 50 ......CNp9.vq..P
0763becc 21 02 54 9e a2 43 da 0e-04 08 12 96 10 95 4a 64 !.T..C........Jd
0763bedc a2 04 d0 33 43 4a e4 d0-be 9d 96 4d 66 b6 78 21 ...3CJ.....Mf.x!
0763beec f1 f5 90 24 3d e3 81 2c-e5 30 92 a9 44 ad ee 8a ...$=..,.0..D...
0763befc 97 ff 07 48 4b 79 a1 7d-3d 44 16 76 9e 4e 84 68 ...HKy.}=D.v.N.h
0763bf0c 9a 06 5a cc 34 14 a6 68-69 c7 fd 1f fe ae 63 64 ..Z.4..hi.....cd
0763bf1c 93 ef ff c2 02 45 3e 20-db 34 0f f0 98 55 e8 12 .....E> .4...U..

通过ba w1 0763beac,发现0x0763beac来源于0x0746ba24,之后就不知道0x0746ba24来源于什么的

而0763beac我们也在poc中找到了这段内容,那这就是从文件读取进来的了

最终再看这张图就很清晰了

总结

漏洞就是经过读取文件,计算,调用GetMemoryBlock,由于最低位都是00,导致获取的指针都指向同一个内存(文中的0x1fb1c850),而free的时候就free两次了。

TTD虽然优点很明显
1、可以无poc,无环境调试漏洞,可以团队协作共享
2、地址都是不变的
3、能够”时间穿梭”

缺点
1、假如程序过大,跟踪文件可能很大,而且调试也是比较占用内存的
2、原始调试者的本地目录可能随着分享的跟踪文件而泄露

参考

https://darungrim.com/research/2019-10-10-vulnerability-root-cause-analysis-with-time-travel-debugging.html
https://www.exploit-db.com/exploits/47279
https://github.com/offensive-security/exploitdb-bin-sploits/raw/master/bin-sploits/47279.zip

打赏专区